<template>
  <span ref="animationDom">{{ defaultStr }}</span>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'

@Component({
  name: 'NumberAnimation'
})
export default class extends Vue {
  @Prop({ default: 0 }) private num!: number
  @Prop({ default: 2 }) private decimal!: number
  @Prop({ default: '-' }) private defaultStr!: string

  @Watch('num')
  onNumChange(val: number) {
    this.setAnimation(val)
  }
  animationInterval: number | null = null
  mounted() {
    this.setAnimation(this.num)
  }
  beforeDestroy() {
    if (this.animationInterval) clearInterval(this.animationInterval)
  }
  setAnimation(val: number) {
    val = Number(val)
    let count = 0
    let showNum = 0
    let animationInterval: number | null = null
    if (this.animationInterval) clearInterval(this.animationInterval)
    if (!val) {
      this.setInnerHTML(this.defaultStr)
      return
    }

    if (val <= 20) {
      animationInterval = setInterval(() => {
        count += 1
        if (count > val) {
          this.setInnerHTML(val.toFixed(this.decimal))
          if (animationInterval) clearInterval(animationInterval)
        } else {
          showNum += 1
          this.setInnerHTML(showNum.toFixed(this.decimal))
        }
      }, 50)
    } else {
      animationInterval = setInterval(() => {
        count += 1
        if (count > 20) {
          this.setInnerHTML(val.toFixed(this.decimal))
          if (animationInterval) clearInterval(animationInterval)
        } else {
          showNum = showNum + val / 20
          this.setInnerHTML(showNum.toFixed(this.decimal))
        }
      }, 50)
    }
    this.animationInterval = animationInterval
  }
  setInnerHTML(str: string) {
    try {
      ;(this.$refs.animationDom as Element).innerHTML = str
    } catch (error) {
      if (this.animationInterval) clearInterval(this.animationInterval)
    }
  }
}
</script>
